package time;

import java.util.Comparator;
import java.util.PriorityQueue;
import objects.GameObject;

/**
 * This class controls the ordering of turns, and is the time system for the game.
 * 
 * @author Kyle_Solo
 */
public class TimeQueue {
	private long currentTime = 0;
	/**
	 * This comparator puts GameObjects with low nextTurn values at the head of the queue. Breaks
	 * ties by putting low id's at the head of the queue.
	 */
	private Comparator<GameObject> nextTurn = new Comparator<GameObject>() {

		@Override
		public int compare(GameObject o1, GameObject o2) {
			if (o2.nextTurn == o1.nextTurn) {
				return o1.uid - o2.uid;
			}
			return (int) (o1.nextTurn - o2.nextTurn);
		}
	};

	private final PriorityQueue<GameObject> queue;

	/**
	 * Creates a new TimeQueue
	 */
	public TimeQueue() {
		queue = new PriorityQueue<GameObject>(10, nextTurn);
	}

	/**
	 * Adds a GameObject to the turn queue. It will start its next turn now.
	 * 
	 * @param gameObject
	 */
	public void add(GameObject gameObject) {
		gameObject.nextTurn = currentTime;
		queue.add(gameObject);
	}

	/**
	 * Adds a GameObject to the turn queue.
	 * 
	 * @param gameObject
	 * @param delay
	 *            the amount of time that this GameObject will be busy doing whatever it started on
	 *            its turn
	 */
	public void add(GameObject gameObject, long delay) {
		gameObject.nextTurn += delay;
		queue.add(gameObject);
	}

	/**
	 * @return the current time
	 */
	public long getCurrentTime() {
		return currentTime;
	}

	/**
	 * @return the GameObject whose turn it is next
	 */
	public GameObject getNextTurn() {
		assert queue != null : "No TimeQueue exists!";
		assert queue.size() > 0 : "The TimeQueue is empty!";
		while (!queue.isEmpty()) {
			GameObject g = queue.poll();
			assert currentTime <= g.nextTurn : "Going back in Time!";
			// update the current time
			currentTime = g.nextTurn;
			return g;
		}
		assert false : "The TimeQueue ran out of GameObjects!";
		// everything is dead
		return null;
	}
}
